home *** CD-ROM | disk | FTP | other *** search
- /* Rendition.c by Martin Boyd 25-Apr-93.
- *
- * An example file saver using the OpalVision LSI interface.
- *
- * The rendition file format simply consists of a 1024 byte
- * header (Described below) followed by 32 bit (RGBA) image data
- * compressed using run-length encoding. Each run is encoded as
- * 6 bytes:
- *
- * Byte 0 - Red
- * Byte 1 - Green
- * Byte 2 - Blue
- * Byte 3 - Alpha
- * Byte 4 - Run length low byte
- * Byte 5 - Run length high byte
- *
- * NOTE: This saver only saves the 6RN format as described
- * above.
- */
-
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <opal/opallib.h>
- #include <opal/loadsave.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <exec/memory.h>
- #include <exec/types.h>
- #include <exec/ports.h>
- #include <exec/nodes.h>
- #include <stdlib.h>
- #include <string.h>
-
-
- char Version[] = "\0$VER: Rendition.Saver 1.0 (25.04.93)";
-
- /* Rendition format information */
-
- struct Tile
- { long Ptr;
- long Length;
- };
-
- struct RendHeader /* 1024 byte header */
- { long Magic; /* H_MAGIC */
- SHORT Version; /* 2 */
- char Label[128]; /* ASCII Desciption */
- char Date[26]; /* Date of image creation */
- SHORT Height; /* Pixel height of image */
- SHORT Width; /* Pixel width of image */
- SHORT TileHeight; /* Pixel height of tile */
- SHORT TileWidth; /* Pixel width of tile */
- SHORT Format; /* See below */
- SHORT Encoding; /* See below */
- long NumRuns; /* Number of runs */
- SHORT BlockSize; /* 1024 */
- SHORT XOffset; /* Horizontal offset */
- SHORT YOffset; /* Vertical offset */
- long CMapLen; /* Number of colour table entries */
- long CMapPtr; /* Pointer to ColourMap */
- char CMapName[64]; /* Colour Map filename */
- struct Tile Tile[64]; /* Tile pointer table */
- char UnSpec[258]; /* Unspecified (reserved) */
- };
-
-
- #define H_MAGIC 0xE880
- #define H_BLOCKSIZE 1024
- #define H_HEADERSIZE 1024
-
- /* Format types */
- #define H_CRGBAPIX 2 /* 4 bytes per pixel */
- #define H_6RUNLH 11 /* 6 bytes per run */
- #define H_2RUN 12 /* 2 bytes per run; colour map in seperate file */
- #define H_2RUNMAP 13 /* 2 bytes per run; colour map in image file */
- #define H_COLOURMAP 20 /* 4 bytes per entry */
- #define H_MIPMAP 22 /* Mip map: header, map table and 4-byte pixels */
- #define H_ONEDRGBA8 23 /* 1D table of 4-byte pixels */
- #define H_ONEDBYTE 24 /* 1D table of bytes */
-
-
- extern struct DosLibrary *DOSBase;
- struct OpalBase *OpalBase;
- struct MsgPort *SavePort;
- int Width,Height;
- char *FileName;
- ULONG SaveFlags;
- struct RendHeader RendHeader;
-
-
- BOOL Do_Save (void);
-
- char SaverName[] = "Rendition";
- char PortName[] = "Rendition_Saver";
-
- char Comment[] = "Written by OpalVision Rendition Saver v1.0";
-
-
- void main (void)
- {
- struct LSIMessage *LSIMesg;
-
- SavePort = CreatePort (PortName,0);
- if (SavePort==NULL)
- exit (10);
- OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
- if (OpalBase==NULL)
- { DeletePort (SavePort);
- exit (10);
- }
-
-
- if (!AddOVSaver (SaverName,SavePort,
- OVSF_ALLOWIMAGE|OVSF_ALLOWALPHA|OVSF_NEEDFILENAME))
- { DeletePort (SavePort);
- CloseLibrary ((struct Library *)OpalBase);
- exit (10);
- }
- CloseLibrary ((struct Library *)OpalBase); /* library must be closed */
- OpalBase = NULL;
-
- while (1)
- { WaitPort (SavePort);
- while (LSIMesg = (struct LSIMessage *)GetMsg (SavePort))
- { switch (LSIMesg->lsi_Type)
- { case OVCMD_SAVEIMAGE:
- Width = LSIMesg->lsi_Width;
- Height = LSIMesg->lsi_Height;
- FileName = LSIMesg->lsi_FileName;
- SaveFlags = LSIMesg->lsi_Flags;
- ReplyMsg ((struct Message *)LSIMesg);
- Do_Save();
- break;
- case OVCMD_EXPUNGE:
- if (!OpalBase)
- OpalBase = (struct OpalBase *)OpenLibrary ("opal.library",0);
- RemOVSaver (SaverName);
- if (OpalBase)
- CloseLibrary ((struct Library *)OpalBase);
- DeletePort (SavePort);
- ReplyMsg ((struct Message *)LSIMesg);
- exit (0);
- break;
- case OVCMD_PARAMETERS:
- /* No parameters */
- break;
- }
- }
- }
- }
-
-
- /* I'm not sure if the format allows run length compression
- * beyond the end of a line, so to be safe I end the compression
- * at the end of each scan line.
- */
-
-
- BOOL Do_Save (void)
- {
- int x,y;
- struct MsgPort *MasterPort;
- struct LSIMessage LSIMesg;
- BPTR File;
- UBYTE *SrcBuff,*DestBuff;
- register UBYTE *D,*R,*G,*B,*A,RData,GData,BData,AData;
- long SBuffSize,DBuffSize,BuffRows,RowsLeft,Size,RunLength;
- struct DateTime DT;
-
-
- /* Get a handle on the Host port */
- MasterPort = FindPort (OVSAVERPORT);
- if (MasterPort==NULL) return (FALSE);
-
- /* Allocate buffers for compression */
- BuffRows = 20;
- SrcBuff = NULL;
- DestBuff = NULL;
- do
- { SBuffSize = BuffRows * Width*4;
- DBuffSize = BuffRows * Width*6;
- SrcBuff = AllocMem (SBuffSize,MEMF_CLEAR);
- if (SrcBuff!=NULL)
- { DestBuff = AllocMem (DBuffSize,MEMF_CLEAR);
- if (DestBuff==NULL)
- { FreeMem (SrcBuff,SBuffSize);
- SrcBuff=NULL;
- }
- }
- if (SrcBuff==NULL) BuffRows--;
- } while ((SrcBuff==NULL) && (DestBuff==NULL) && (BuffRows>0));
-
- if (BuffRows==0)
- { LSIMesg.lsi_Type = OVCMD_ERROR;
- LSIMesg.lsi_Result = LSI_ERR_OUTOFMEM;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- return (FALSE);
- }
-
- memset (&LSIMesg,0,sizeof(struct LSIMessage));
- LSIMesg.lsi_Node.mn_Node.ln_Type = NT_MESSAGE;
- LSIMesg.lsi_Node.mn_ReplyPort = SavePort;
- LSIMesg.lsi_Node.mn_Length = sizeof (struct LSIMessage);
-
- File = Open (FileName,MODE_NEWFILE);
- if (File==NULL)
- { FreeMem (SrcBuff,SBuffSize);
- FreeMem (DestBuff,DBuffSize);
- LSIMesg.lsi_Type = OVCMD_ERROR;
- LSIMesg.lsi_Result = LSI_ERR_OPENFILE;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- return (FALSE);
- }
-
- /* Initialise File Header */
- memset (&RendHeader,0,sizeof(struct RendHeader));
- RendHeader.Magic = H_MAGIC;
- RendHeader.Version = 2;
- strcpy (RendHeader.Label,Comment);
- if (DOSBase->dl_lib.lib_Version>=36)
- { DateStamp (&DT.dat_Stamp);
- DT.dat_Format = FORMAT_DOS;
- DT.dat_Flags = 0;
- DT.dat_StrDay = NULL;
- DT.dat_StrDate = RendHeader.Date;
- DT.dat_StrTime = &RendHeader.Date[10];
- DateToStr (&DT);
- RendHeader.Date[9] = ' ';
- }
- RendHeader.Width = Width;
- RendHeader.Height = Height;
- RendHeader.Format = H_6RUNLH;
- Size = sizeof (struct RendHeader);
-
- /* Write the header */
- if (Write (File,&RendHeader,Size)!=Size)
- { FreeMem (SrcBuff,SBuffSize);
- FreeMem (DestBuff,DBuffSize);
- Close (File);
- LSIMesg.lsi_Type = OVCMD_ERROR;
- LSIMesg.lsi_Result = LSI_ERR_FILEWRITE;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- return (FALSE);
- }
-
- /* Compress and Write the body */
- RowsLeft=0;
- D = DestBuff;
-
- for (y=0; y<Height; y++)
- { if (RowsLeft==0)
- { if (y>0)
- { Size = D-DestBuff;
- if (Write (File,DestBuff,Size)!=Size)
- { FreeMem (SrcBuff,SBuffSize);
- FreeMem (DestBuff,DBuffSize);
- Close (File);
- LSIMesg.lsi_Type = OVCMD_ERROR;
- LSIMesg.lsi_Result = LSI_ERR_FILEWRITE;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- return (FALSE);
- }
- }
- /* Get some image data (in RGB) */
- D = DestBuff;
- R = SrcBuff;
- G = SrcBuff + BuffRows*Width;
- B = SrcBuff + (2*BuffRows*Width);
- A = SrcBuff + (3*BuffRows*Width);
- LSIMesg.lsi_Width = Width;
- LSIMesg.lsi_Height = BuffRows;
- LSIMesg.lsi_X = 0;
- LSIMesg.lsi_Y = y;
- LSIMesg.lsi_Type = OVCMD_GETDATA;
- LSIMesg.lsi_SubType = OVDF_RGB;
- LSIMesg.lsi_Planes[0] = R;
- LSIMesg.lsi_Planes[1] = G;
- LSIMesg.lsi_Planes[2] = B;
- LSICmd (MasterPort,SavePort,&LSIMesg);
-
- /* If image has an Alpha chanel, get alpha
- * data, else set Alpha to 0xFF
- */
-
- if (SaveFlags & LSIF_ALPHA)
- { LSIMesg.lsi_SubType = OVDF_ALPHA;
- LSIMesg.lsi_Planes[0] = A;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- }
- else
- { for (x=BuffRows*Width; x>0; x--)
- *A++ = 0xFF;
- A = SrcBuff + (3*BuffRows*Width);
- }
- RowsLeft = BuffRows;
- }
- RData = *R++;
- GData = *G++;
- BData = *B++;
- AData = *A++;
- RunLength = 1;
- for (x=1; x<Width; x++)
- { if ((*R==RData) && (*G==GData) && (*B==BData) &&
- (*A==AData))
- { RunLength++;
- R++; G++; B++; A++;
- }
- else
- { *D++ = RData;
- *D++ = GData;
- *D++ = BData;
- *D++ = AData;
- *D++ = RunLength & 0xFF;
- *D++ = (RunLength>>8) & 0xFF;
- RData = *R++;
- GData = *G++;
- BData = *B++;
- AData = *A++;
- RunLength = 1;
- }
- }
- *D++ = RData;
- *D++ = GData;
- *D++ = BData;
- *D++ = AData;
- *D++ = RunLength & 0xFF;
- *D++ = (RunLength>>8) & 0xFF;
-
- if ((y & 0xF)==0)
- { LSIMesg.lsi_Type = OVCMD_PERCENTAGE;
- LSIMesg.lsi_Address = "Rend ";
- LSIMesg.lsi_Result = (y*100)/Height;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- }
- RowsLeft--;
- }
-
- /* Write out whatever's left */
- Size = D-DestBuff;
- if (Size>0)
- Write (File,DestBuff,Size);
-
- LSIMesg.lsi_Type = OVCMD_DONE;
- LSICmd (MasterPort,SavePort,&LSIMesg);
- Close (File);
- FreeMem (SrcBuff,SBuffSize);
- FreeMem (DestBuff,DBuffSize);
- return (TRUE);
- }
-
-
-
-